package com.hyacinth.server.interceptor;

import com.hyacinth.server.action.param.Param;
import com.hyacinth.server.config.AppConfig;
import com.hyacinth.server.context.AuroraContext;
import com.hyacinth.server.util.ClassScanner;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 拦截处理器
 * 单实例
 * @author zhangfb
 * @version 1.0.0.1
 * @since JDK 1.8
 */
public class InterceptProcess {

    private List<AuroraIntercept> interceptList;
    private volatile static InterceptProcess process;
    private InterceptProcess(){}

    // 获取实例对象
    public static InterceptProcess getInstance() {
        if (process == null) {
            synchronized (AuroraIntercept.class) {
                if (process == null) {
                    process = new InterceptProcess();
                }
            }
        }
        return process;
    }

    /**
     * 加载所有的拦截器
     */
    public void loadIntercept() throws Exception {
        if (interceptList == null) {
            interceptList = new ArrayList<>(10);
            // 扫描拦截器
            Map<Class<?>, Integer> interceptors = ClassScanner.getAuroraInterceptor(AppConfig.getInstance().getRootPackageName());
            for (Map.Entry<Class<?>, Integer> entry : interceptors.entrySet()) {
                AuroraIntercept intercept = (AuroraIntercept) entry.getKey().newInstance();
                intercept.setOrder(entry.getValue());
                interceptList.add(intercept);
            }
            // 按order排序
            interceptList = interceptList.stream()
                    .sorted(Comparator.comparing(AuroraIntercept::getOrder))
                    .collect(Collectors.toList());
        }
    }

    /**
     * 前置处理
     * @return 处理结果
     *   true 成功 | false 失败
     */
    public boolean beforeProcess(Param param) {
        for (AuroraIntercept intercept : interceptList) {
            boolean access = intercept.before(AuroraContext.getContext(), param);
            if (!access) {
                return false;
            }
        }
        return true;
    }

    /**
     * 后置处理
     */
    public void afterProcess(Param param) {
        for (AuroraIntercept intercept : interceptList) {
            intercept.after(AuroraContext.getContext(), param);
        }
    }
}
